Matematyczne modelowanie procesów decyzyjnych w finansach
Rafał Głodek, Joanna Kusy, Oliwia Makuch, Tomasz Srebniak
Teoria portfelowa
…po angielsku modern portfolio theory lub mean–variance analysis.
Główna idea – Efektywna granica
…czyli Efficient frontier.
To zbiór porfeli, dla których nie istnieje inny portfel o wyższym oczekiwanym zwrocie przy tym samym odchyleniu standardowym zwrotu (ryzyku).
Szukamy takich wag, które pozwolą nam zminimalizować wariancję
\[
\min_{\mathbf{w}} = \mathbf{w}^T\Sigma\mathbf{w}.
\]
Dla dobranych wag wartość oczekiwana zwrotu powinna odpowiadać ustalonemu poziomowi
\[
\mathbf{w}^T\mathbf{\mu} = \mu_p.
\]
Wagi muszą sumować się do 1
\[
\mathbf{w}^T\mathbf{1}=1.
\]
Biblioteka PyortfolioOpt
Jak wyglądają nasze dane?
AAPL GE AMD ... BBY PFE JPM
date ...
1989-12-29 0.117203 0.352438 3.9375 ... 0.166287 0.110818 1.827968
1990-01-02 0.123853 0.364733 4.1250 ... 0.173216 0.113209 1.835617
1990-01-03 0.124684 0.364050 4.0000 ... 0.194001 0.113608 1.896803
[3 rows x 10 columns]
Importujemy potrzebne funkcje
from pypfopt import expected_returns
from pypfopt import risk_models
Liczymy średnie zwroty dla danych…
mu = expected_returns.mean_historical_return(stock_prices)
Pierwsze 5 wyników dla średnich zwrotów
AAPL 0.294305
GE 0.136009
AMD 0.032850
WMT 0.120012
BAC 0.105540
dtype: float64
Liczymy macierz kowariancji zwrotów dla danych…
Sigma = risk_models.sample_cov(stock_prices)
Pierwsze 5 wyników dla macierzy kowariancji
AAPL GE AMD WMT BAC
AAPL 0.207537 0.038348 0.084594 0.026599 0.046262
GE 0.038348 0.083109 0.048893 0.029263 0.063275
AMD 0.084594 0.048893 0.390586 0.027288 0.068712
WMT 0.026599 0.029263 0.027288 0.069092 0.030757
BAC 0.046262 0.063275 0.068712 0.030757 0.180192
Wybór portfela
from pypfopt.efficient_frontier import EfficientFrontier
Liczymy Efficient frontier…
ef_return = EfficientFrontier(mu, Sigma)
ef_sharpe = EfficientFrontier(mu, Sigma)
ef_vol = EfficientFrontier(mu, Sigma)
Wybieramy porfel o rocznej stopie zwrotu 20%…
ef_return.efficient_return(0.2)
Wagi
ef_return.clean_weights()
AAPL: 0.16759
GE: 0.00000
AMD: 0.00000
WMT: 0.08029
BAC: 0.00000
T: 0.05185
XOM: 0.28483
BBY: 0.07526
PFE: 0.34018
JPM: 0.00000
Statystyki
ef_return.portfolio_performance(verbose=True)
Expected annual return: 20.0%
Annual volatility: 19.9%
Sharpe Ratio: 1.01
(np.float64(0.19999999999999996), np.float64(0.19898336191007596), np.float64(1.0051091612894922))
Wybieramy porfel o najwyższym wskaźniku Sharpe’a…
Wagi
AAPL: 0.20430
GE: 0.00000
AMD: 0.00000
WMT: 0.03511
BAC: 0.00000
T: 0.00000
XOM: 0.26966
BBY: 0.09112
PFE: 0.39980
JPM: 0.00000
Statystyki
Expected annual return: 21.5%
Annual volatility: 21.3%
Sharpe Ratio: 1.01
(np.float64(0.21532248096661108), np.float64(0.2127665321341155), np.float64(1.0120129270654488))
Wybieramy porfel o najmniejszej zmienności (odchyleniu standardowym zwrotów)…
Wagi
AAPL: 0.04306
GE: 0.05511
AMD: 0.00000
WMT: 0.21254
BAC: 0.00000
T: 0.21768
XOM: 0.31582
BBY: 0.01963
PFE: 0.13616
JPM: 0.00000
Statystyki
Expected annual return: 14.8%
Annual volatility: 17.7%
Sharpe Ratio: 0.84
(np.float64(0.14823493562996315), np.float64(0.17710888575470815), np.float64(0.8369706296682664))
Alternatywne sposoby obliczania średniej i wariancji
Zwroty i ryzyko ważone wykładniczo
Nadajemy większe wagi nowym danym.
mu_exp = expected_returns.ema_historical_return(stock_prices, span=180,
frequency=252)
Sigma_exp = risk_models.exp_cov(stock_prices, span=180, frequency=252)
ef_exp = EfficientFrontier(mu_exp, Sigma_exp)
ef_exp.max_sharpe()
Statystyki
Expected annual return: 35.8%
Annual volatility: 23.3%
Sharpe Ratio: 1.54
(np.float64(0.35775845787745103), np.float64(0.2330451766369705), np.float64(1.5351463739357045))
Semikowariancja
… czyli wariancja ze zwrotów poniżej ustalonego benchamrku.
semi_Sigma = risk_models.semicovariance(stock_prices,
benchmark=0, frequency=252)
Pierwsze 5 wyników dla macierzy semikowariancji
AAPL GE AMD WMT BAC
AAPL 0.092904 0.025240 0.059902 0.021780 0.033612
GE 0.025240 0.036607 0.037300 0.017666 0.034130
AMD 0.059902 0.037300 0.178330 0.027033 0.052319
WMT 0.021780 0.017666 0.027033 0.031344 0.021281
BAC 0.033612 0.034130 0.052319 0.021281 0.080705